package com.xingda.packing.domain;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xingda.packing.common.PackUtils;
import com.xingda.packing.events.EventCreater;
import com.xingda.packing.minitor.dto.PkWheelDto;
import com.xingda.packing.minitor.entity.*;
import com.xingda.packing.minitor.mapper.*;
import com.xingda.packing.minitor.service.IPkAlarmHistoryService;
import com.xingda.packing.plc.service.PlcDirectiveService;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 产品包装区
 */
@Data
@Slf4j
@Component
public class ProductArea implements Serializable {

    private static final long serialVersionUID = -4462479920371523307L;
    @Value("${com.xingda.boxLocation.leftMinNo}")
    @Getter
    private Integer leftMinNo;
    @Value("${com.xingda.boxLocation.leftMaxNo}")
    @Getter
    private Integer leftMaxNo;
    @Value("${com.xingda.boxLocation.rightMinNo}")
    @Getter
    private Integer rightMinNo;
    @Value("${com.xingda.boxLocation.rightMaxNo}")
    @Getter
    private Integer rightMaxNo;
    @Value("${com.xingda.model}")
    @Getter
    private String model;

    @Resource
    PkBoxLocationRealtionMapper pkBoxLocationRealtionMapper;

    @Resource
    PkBoxLocationMapper pkBoxLocationMapper;

    @Resource
    PkTaskMapper pkTaskMapper;

    @Resource
    PkTaskInfoMapper pkTaskInfoMapper;

    @Resource
    PkTaskDemandMapper pkTaskDemandMapper;

    @Resource
    PkWheelMapper pkWheelMapper;

    @Resource
    PkTaskBomMapper pkTaskBomMapper;

    @Resource
    PlcDirectiveService plcDirectiveService;

    @Resource
    EventCreater eventCreater;

    @Resource
    IPkAlarmHistoryService pkAlarmHistoryService;

    /**
     * 产品区箱位列表
     */
    @Setter(AccessLevel.NONE)
    List<ProductBoxLocation> locationList1;
    @Setter(AccessLevel.NONE)
    List<ProductBoxLocation> locationList2;
    @Setter(AccessLevel.NONE)
    List<ProductBoxLocation> locationList3;

    public List<ProductBoxLocation> getLocationList(int area) {
        if (area == 1) {
            return locationList1;
        } else if (area == 2) {
            return locationList2;
        } else if (area == 3){
            return locationList3;
        } else {
            return null;
        }
    }

    public HashMap<String, Integer> leftProductMap = new HashMap<>();
    public HashMap<String, Integer> leftNotProductMap = new HashMap<>();

    public HashMap<String, Integer> rightProductMap = new HashMap<>();
    public HashMap<String, Integer> rightNotProductMap = new HashMap<>();

    public HashMap<String, Integer> getProductMap(int area) {
        if (area == 1) {
            return leftProductMap;
        } else {
            return rightProductMap;
        }
    }

    public HashMap<String, Integer> getNotProductMap(int area) {
        if (area == 1) {
            return leftNotProductMap;
        } else {
            return rightNotProductMap;
        }
    }

    public void saveWheelTagToProductMap(String wheelTag, int area, int type) {
        if (area == 1) {
            if (type == 5) {
                if (leftNotProductMap.containsKey(wheelTag)) {
                    leftNotProductMap.put(wheelTag, leftNotProductMap.get(wheelTag) + 1);
                } else {
                    leftNotProductMap.put(wheelTag, 1);
                }
            } else {
                if (leftProductMap.containsKey(wheelTag)) {
                    leftProductMap.put(wheelTag, leftProductMap.get(wheelTag) + 1);
                } else {
                    leftProductMap.put(wheelTag, 1);
                }
            }

        } else {
            if (type == 5) {
                if (rightNotProductMap.containsKey(wheelTag)) {
                    rightNotProductMap.put(wheelTag, rightNotProductMap.get(wheelTag) + 1);
                } else {
                    rightNotProductMap.put(wheelTag, 1);
                }
            } else {
                if (rightProductMap.containsKey(wheelTag)) {
                    rightProductMap.put(wheelTag, rightProductMap.get(wheelTag) + 1);
                } else {
                    rightProductMap.put(wheelTag, 1);
                }
            }

        }
    }

    public void removeWheelFromMap(String wheelTag, int area, int type) {
        if (area == 1) {
            if (type == 5) {
                if (leftNotProductMap.get(wheelTag) == 1) {
                    leftNotProductMap.remove(wheelTag);
                } else {
                    leftNotProductMap.put(wheelTag, leftNotProductMap.get(wheelTag) - 1);
                }
            } else {
                if (leftProductMap.get(wheelTag) == 1) {
                    leftProductMap.remove(wheelTag);
                } else {
                    leftProductMap.put(wheelTag, leftProductMap.get(wheelTag) - 1);
                }
            }

        } else {
            if (type == 5) {
                if (rightNotProductMap.get(wheelTag) == 1) {
                    rightNotProductMap.remove(wheelTag);
                } else {
                    rightNotProductMap.put(wheelTag, rightNotProductMap.get(wheelTag) - 1);
                }
            } else {
                if (rightProductMap.get(wheelTag) == 1) {
                    rightProductMap.remove(wheelTag);
                } else {
                    rightProductMap.put(wheelTag, rightProductMap.get(wheelTag) - 1);
                }
            }

        }
    }

    public boolean canSaveTask(int area, String wheelTagMap, int boxLocationId) {
        HashMap<String, Integer> productMap = getProductMap(area);
        //查询当前装箱位关联的任务
        LambdaQueryWrapper<PkBoxLocationRealtion> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(PkBoxLocationRealtion::getBoxLocationId, boxLocationId);
        PkBoxLocationRealtion pkBoxLocationRealtion = pkBoxLocationRealtionMapper.selectOne(lambdaQueryWrapper);
        if (Objects.nonNull(pkBoxLocationRealtion)) {
            //判断要保存的和原有的是否相等
            PkTask pkTask = pkTaskMapper.selectById(pkBoxLocationRealtion.getTaskId());
            return !pkTask.getWheelTagMap().equals(wheelTagMap);
        } else {
            //不存在 新装箱 查询已有的装箱数量是不是小于5
            return productMap.values().stream().mapToInt(i -> i).sum() < 7;
        }
    }

    public ProductArea() {
        this.locationList1 = new ArrayList<>();
        this.locationList2 = new ArrayList<>();
    }

    /**
     * 装箱位满的报警
     */
    public void triggerFullAlarm(int area) {
        for (ProductBoxLocation productBoxLocation : getLocationList(area)) {
            productBoxLocation.triggerFullAlarm(area);
        }
    }

    /**
     * 根据位置获取产品包装箱
     */
    public Optional<ProductBox> getProductBox(int locationNo) {
        if (locationNo < 11) { 
            return locationList1.stream().filter(location -> location.getLocationNo() == locationNo).map(ProductBoxLocation::getProductBox).findFirst();
        } else {
            return locationList2.stream().filter(location -> location.getLocationNo() == locationNo).map(ProductBoxLocation::getProductBox).findFirst();
        }
    }

    /**
     * 根据位置获取产品包装位
     */
    public Optional<ProductBoxLocation> getProductBoxLocation(int locationNo) {

//        测试用
        log.info("==== locationNo:{}, model:{}", locationNo, model);
        if (model.equals("DMDS")) {
//            双机双分流
            if (locationNo < 11) {
                return locationList1.stream().filter(location -> location.getLocationNo() == locationNo).findFirst();
            } else {
                return locationList2.stream().filter(location -> location.getLocationNo() == locationNo).findFirst();
            }
        } else if (model.equals("DMSS")) {
//            双机单分流
            if (locationNo < 7) {
                return locationList1.stream().filter(location -> location.getLocationNo() == locationNo).findFirst();
            } else {
                return locationList2.stream().filter(location -> location.getLocationNo() == locationNo).findFirst();
            }
        } else if (model.equals("TMSS")) {
//            三机单分流   --- 新一厂十一线
            if (locationNo < 7) {
                return locationList1.stream().filter(location -> location.getLocationNo() == locationNo).findFirst();
            } else if (locationNo > 12) {
                return locationList3.stream().filter(location -> location.getLocationNo() == locationNo).findFirst();
            } else {
                return locationList2.stream().filter(location -> location.getLocationNo() == locationNo).findFirst();
            }

        }
        return Optional.empty();
    }

    /**
     * 放置产品包装箱
     *
     * @param locationNo 位置编号
     * @param productBox 产品包装箱
     */
    public void putBox(int locationNo, ProductBox productBox) {
        Optional<ProductBoxLocation> locationOptional;
        if (locationNo < 11) {
            locationOptional = locationList1.stream().filter(location -> location.getLocationNo() == locationNo).findFirst();
        } else {
            locationOptional = locationList2.stream().filter(location -> location.getLocationNo() == locationNo).findFirst();
        }
        if (locationOptional.isPresent()) {
            locationOptional.get().setProductBox(productBox);
        } else {
            log.error("放置产品包装箱失败：产品区位置{}不存在", locationNo);
        }
    }

    public void removeBox(int locationNo) {
        if (locationNo < 11) {
            Optional<ProductBoxLocation> first = locationList1.stream().filter(location -> location.getLocationNo() == locationNo).findFirst();
            first.ifPresent(productBoxLocation -> removeWheelFromMap(productBoxLocation.getBox().getWheelTagMap(), 1, productBoxLocation.getBox().getType()));
            first.ifPresent(location -> locationList1.remove(location));
        } else {
            Optional<ProductBoxLocation> first = locationList2.stream().filter(location -> location.getLocationNo() == locationNo).findFirst();
            first.ifPresent(productBoxLocation -> removeWheelFromMap(productBoxLocation.getBox().getWheelTagMap(), 2, productBoxLocation.getBox().getType()));
            first.ifPresent(location -> locationList2.remove(location));
        }
    }

    public boolean isAlreadyPacking(String barCode) {
        LambdaQueryWrapper<PkWheel> wheelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wheelLambdaQueryWrapper.eq(PkWheel::getBarCode, barCode);
        List<PkWheel> pkWheels = pkWheelMapper.selectList(wheelLambdaQueryWrapper);
        if (pkWheels.isEmpty()) {
            return false;
        }
        LambdaQueryWrapper<PkTaskInfo> pkTaskInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        List<Integer> collect = pkWheels.stream().map(PkWheel::getId).collect(Collectors.toList());
        pkTaskInfoLambdaQueryWrapper.in(PkTaskInfo::getWheelId, collect);
        List<PkTaskInfo> pkTaskInfos = pkTaskInfoMapper.selectList(pkTaskInfoLambdaQueryWrapper);
        return !pkTaskInfos.isEmpty();
    }

    /**
     * 产品包装去启动时初始化加载所有装箱位
     */
    public void initStatus(int area) {
        initStatus(0, area);
    }

    /**
     * 加载指定装箱位
     *
     * @param relationId 关联id
     */
    public void initStatus(int relationId, int area) {
        //查询所有装箱关联信息
        LambdaQueryWrapper<PkBoxLocationRealtion> pkBoxLocationRealtionQueryWrapper = Wrappers.lambdaQuery();
        if (relationId > 0) {
            pkBoxLocationRealtionQueryWrapper.eq(PkBoxLocationRealtion::getId, relationId);
        } else {
            if (area == 1) {
                pkBoxLocationRealtionQueryWrapper.between(PkBoxLocationRealtion::getBoxLocationId, 1, 10);
            } else {
                pkBoxLocationRealtionQueryWrapper.between(PkBoxLocationRealtion::getBoxLocationId, 11, 20);
            }
        }
        pkBoxLocationRealtionQueryWrapper.orderByAsc(PkBoxLocationRealtion::getDt);
        List<PkBoxLocationRealtion> pkBoxLocationRealtions = pkBoxLocationRealtionMapper.selectList(pkBoxLocationRealtionQueryWrapper);
        if (Objects.isNull(pkBoxLocationRealtions) || pkBoxLocationRealtions.isEmpty()) {
            log.info("无装箱位关联信息！");
            return;
        }
        pkBoxLocationRealtions.forEach(pkBoxLocationRealtion -> {
            //箱号
            Integer boxLocationId = pkBoxLocationRealtion.getBoxLocationId();
            //任务id
            Integer taskId = pkBoxLocationRealtion.getTaskId();
            // 存储的装箱位信息
            PkBoxLocation pkBoxLocation = pkBoxLocationMapper.selectById(boxLocationId);
            // 存储的任务信息
            PkTask pkTask = pkTaskMapper.selectById(taskId);
            // 装载装箱位信息赋值
            ProductBox box = new ProductBox();
            box.setRequireCount(pkTask.getBoxWheelSum());
            box.setRequireFloorCount(pkTask.getLayer());
            box.setFloorLocationCount(pkTask.getFloorCount());
            box.setWheelTypeId(pkTask.getWheelTypeId());
            box.setType(pkTask.getType());
            box.setWheelTag(pkTask.getWheelTag());
            box.setWheelTagMap(pkTask.getWheelTagMap());
            box.setCustomer(pkTask.isCustomer());
            box.setConsumerName(pkTask.getCustomerName());
            box.setTaskId(pkTask.getId());
            box.setBoxNo(pkTask.getBoxNo());
            if (boxLocationId > 10) {
                saveWheelTagToProductMap(pkTask.getWheelTagMap(), 2, pkTask.getType());
            } else {
                saveWheelTagToProductMap(pkTask.getWheelTagMap(), 1, pkTask.getType());
            }
            // 装载装箱规则
            LambdaQueryWrapper<PkTaskDemand> pkTaskDemandLambdaQueryWrapper = Wrappers.lambdaQuery();
            pkTaskDemandLambdaQueryWrapper.eq(PkTaskDemand::getTaskId, pkTask.getId());
            List<PkTaskDemand> pkTaskDemandList = pkTaskDemandMapper.selectList(pkTaskDemandLambdaQueryWrapper);
            PackDemand demand = PackUtils.toPackDemand(pkTaskDemandList);
            demand.setSurfaceLr(pkTask.getSurfaceLr());
            box.setPackDemand(demand);
            // 装载工字轮信息
            List<PkWheelDto> wheelMaps = pkWheelMapper.getPkWheelByTaskId(taskId);
            if (wheelMaps != null && !wheelMaps.isEmpty() && wheelMaps.get(0) != null) {
                for (PkWheelDto pkWheelDto : wheelMaps) {
                    Wheel wheel = PackUtils.toWheel(pkWheelDto);
                    box.putWheel(wheel);
                }
            }
            // 装载允许装箱物料编号
            LambdaQueryWrapper<PkTaskBom> taskBomQueryWrapper = Wrappers.lambdaQuery();
            taskBomQueryWrapper.eq(PkTaskBom::getPkTaskId, taskId);
            List<PkTaskBom> list = pkTaskBomMapper.selectList(taskBomQueryWrapper);
            if (!CollectionUtils.isEmpty(list)) {
                List<String> pkBomPkInvbasdocList = list.stream().map(PkTaskBom::getPkBomPkInvbasdoc).collect(Collectors.toList());
                box.setPkInvbasdocList(pkBomPkInvbasdocList);
            }
            Optional<ProductBox> productBoxOpt = this.getProductBox(pkBoxLocation.getBoxLocationNo());
            if (!productBoxOpt.isPresent()) {
                if (pkBoxLocation.getBoxLocationNo() < 11) {
                    this.getLocationList1().add(new ProductBoxLocation(pkBoxLocation.getBoxLocationNo(), pkBoxLocation.getPalletPhotoFinish(), pkBoxLocation.getPalletComing(), this.plcDirectiveService, this.eventCreater));
                } else {
                    this.getLocationList2().add(new ProductBoxLocation(pkBoxLocation.getBoxLocationNo(), pkBoxLocation.getPalletPhotoFinish(), pkBoxLocation.getPalletComing(), this.plcDirectiveService, this.eventCreater));
                }
            }
            this.putBox(pkBoxLocation.getBoxLocationNo(), box);
        });
    }
}
